package view.editorview;

import javax.swing.ImageIcon;
import javax.swing.tree.DefaultMutableTreeNode;

import model.LogicType;
import view.UtilityConstants;

/**
 * <b>Erbt:</b> <code>DefaultMutableTreeNode</code> <br>
 * <b>Funktion:</b> Repraesentiert die Bauteilauswahlliste<br>
 * <br>
 * Repraesentiert die Bauteilauswahlliste. Die von dieser Klasse erzeugten
 * Objekte werden im <code>ComponentPanel</code> verwendet.
 * 
 * @author Team Locsi
 * 
 */
@SuppressWarnings("serial")
public class ComponentTree extends DefaultMutableTreeNode {

	/*
	 * Rubriken fuer vordefinierte Bauteile und selbstdefinierte Bauteile
	 */
	private DefaultMutableTreeNode preDef;
	private DefaultMutableTreeNode selfDef;

	/**
	 * Dieser Konstruktor erzeugt ein neues <code>ComponentTree</code>-Objekt.
	 * 
	 * @param text
	 *            <code>String</code> - Bezeichnung fuer den
	 *            <code>ComponentTree</code>
	 */
	public ComponentTree(String text) {
		super(text);
		preDef = new DefaultMutableTreeNode("Vordefinierte Bauteile");
		selfDef = new DefaultMutableTreeNode("Selbstdefinierte Bauteile");
		
		// Fuer jeden Typ der existiert wird ein Component Node erzeugt und zum
		// Knoten "Vordefinierte Bauteile" hinzugefuegt
		for (LogicType l : LogicType.values()) {
			if (l != LogicType.SELFDEFINED) {
				preDef.add(new ComponentNode(l, null));
			}
		}
		preDef.add(new ComponentNode(null, "Leitung"));
		this.add(preDef);
		
		// Die selbstdefinierten Elemente werden im ComponentPanel in der 
		// update Methode hinzugefuegt
		this.add(selfDef);
	}

	

	/**
	 * Diese Methode gibt die Icons fuer die jeweiligen Knoten zurueck.
	 * 
	 * @param value
	 *            <code>LogicType</code> - Typ des Bauteils; falls
	 *            <code>null</code>, so wird <code>Icon</code> fuer eine
	 *            <i>Verbindung</i> zurueckgegeben.
	 * @return <code>ImageIcon</code> - abhaengig vom Wert des Parameters, wird
	 *         das zugehoerige <code>Icon</code> zurueckgegeben.
	 */
	private ImageIcon getIconPath(LogicType value) {
		// null steht fuer eine Verbindung, da diese keinen eigenen LogicType 
		// besitzt
		if (value == null) {
			return new ImageIcon(getClass().getClassLoader().getResource(UtilityConstants.TREEICON_PATH + "wireSmallImage.png"));
		}
		switch (value) {
		case AND:
			return new ImageIcon(getClass().getClassLoader().getResource(UtilityConstants.TREEICON_PATH + "andSmallImage.png"));
		case OR:
			return new ImageIcon(getClass().getClassLoader().getResource(UtilityConstants.TREEICON_PATH + "orSmallImage.png"));
		case NOT:
			return new ImageIcon(getClass().getClassLoader().getResource(UtilityConstants.TREEICON_PATH + "notSmallImage.png"));
		case XOR:
			return new ImageIcon(getClass().getClassLoader().getResource(UtilityConstants.TREEICON_PATH + "xorSmallImage.png"));
		case NAND:
			return new ImageIcon(getClass().getClassLoader().getResource(UtilityConstants.TREEICON_PATH + "nandSmallImage.png"));
		case TWO_MX:
			return new ImageIcon(getClass().getClassLoader().getResource(UtilityConstants.TREEICON_PATH + "tmxSmallImage.png"));
		case FLIPFLOP:
			return new ImageIcon(getClass().getClassLoader().getResource(UtilityConstants.TREEICON_PATH + "ffSmallImage.png"));
		case NODE:
			return new ImageIcon(getClass().getClassLoader().getResource(UtilityConstants.TREEICON_PATH + "bommSmallImage.png"));
		case CLOCK:
			return new ImageIcon(getClass().getClassLoader().getResource(UtilityConstants.TREEICON_PATH + "clockSmallImage.png"));
		case LAMP:
			return new ImageIcon(getClass().getClassLoader().getResource(UtilityConstants.TREEICON_PATH + "lampSmallImage.png"));
		case SWITCH:
			return new ImageIcon(getClass().getClassLoader().getResource(UtilityConstants.TREEICON_PATH + "switchSmallImage.png"));
		case SELFDEFINED:
			return new ImageIcon(getClass().getClassLoader().getResource(UtilityConstants.TREEICON_PATH + "sdSmallImage.png"));
		default:
			return null;
		}
	}

	/**
	 * Gibt den Wurzelknoten fuer selbstdefinierte Bauteile zurueck
	 * 
	 * @return selfDef
	 */
	public DefaultMutableTreeNode getSelfDef() {
		return selfDef;
	}

	/**
	 * Diese innere Klasse repraesentiert einen Knoten im
	 * <code>ComponentTree</code>.
	 * 
	 * @author Team Locsi
	 * 
	 */
	class ComponentNode extends DefaultMutableTreeNode {

		private String text;
		private ImageIcon icon;

		/**
		 * Dieser Konstruktor erzeugt ein neues <code>ComponentNode</code>
		 * -Objekt.
		 * 
		 * @param value
		 *            <code>LogicType</code> - Typ des Bauteils
		 * @param text
		 *            <code>String</code> - Name fuer den Knoten, der in der
		 *            Bauteilauswahlliste angezeigt werden soll
		 */
		public ComponentNode(LogicType value, String text) {
			super(value);
			this.text = text;
			this.icon = getIconPath(value);
		}

		/**
		 * Setzt den Text des <code>ComponentNode</code> fuer die Anzeige in der
		 * Bauteilauswahlliste.
		 * 
		 * @param text
		 *            <code>String</code> - Name fuer den Knoten, der in der
		 *            Bauteilauswahlliste angezeigt werden soll
		 */
		public void setText(String text) {
			this.text = text;
		}

		/**
		 * Gibt den Text des <code>ComponentNode</code> zurueck.
		 * 
		 * @return <code>String</code> - den Text des <code>ComponentNode</code>
		 */
		public String getText() {
			return text;
		}

		/**
		 * Falls der <code>text</code> des <code>ComponentNode</code> nicht
		 * gesetzt wurde, wird der logische Typ des <code>ComponentNode</code>
		 * zurueckgegeben; andernfalls wird <code>text</code> zurueckgegeben.
		 */
		@Override
		public String toString() {
			if (this.getUserObject() instanceof LogicType) {
				if (((LogicType) this.getUserObject()) == LogicType.SELFDEFINED) {
					return text;
				} else {
					return ((LogicType) this.getUserObject()).toString();
				}
			} else {
				return text;
			}
		}

		/**
		 * Setzt das Icon des <code>ComponentNode</code>, das in der
		 * Bauteilauswahlliste angezeigt werden soll.
		 * 
		 * @param icon
		 *            <code>ImageIcon</code> - das Icon das angezeigt werden
		 *            soll.
		 */
		public void setIcon(ImageIcon icon) {
			this.icon = icon;
		}

		/**
		 * Gibt das Icon des <code>ComponentNode</code> zurueck.
		 * 
		 * @return <code>ImageIcon</code> - das Icon des
		 *         <code>ComponentNode</code>.
		 */
		public ImageIcon getIcon() {
			return icon;
		}
	}
}